package com.haltakov.letterjumble.server;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

import com.haltakov.letterjumble.game.api.BoardWord;
import com.haltakov.letterjumble.game.api.Letter;
import com.haltakov.letterjumble.game.api.WordDirection;

/* Handle messages from the client.

Upon initial connection:
    response to client is:
          ok <playerID>   or    full
    message to other client if player is accepted:
          added <playerID>

Other client messages:
* disconnect
  message to other client:
          removed <playerID>
    
* try <posn>
  response to client
     tooFewPlayers
   message to other client if turn accepted
     otherTurn <playerID> <posn>
*/

public class PlayerServerHandler extends Thread {

	private LetterJumbleServer server;
	private Socket clientSock;
	private BufferedReader in;
	private PrintWriter out;

	private int playerID; // this player id is assigned by FBFServer

	public PlayerServerHandler(Socket socket, LetterJumbleServer server) {

		clientSock = socket;
		this.server = server;
		System.out.println("Player connection request");
		try {
			in = new BufferedReader(new InputStreamReader(clientSock.getInputStream()));
			out = new PrintWriter(clientSock.getOutputStream(), true); // autoflush
		} catch (Exception e) {
			System.out.println(e);
		}
	}

	/*
	 * Add this player to LetterJumbleServer array, get an ID, then start
	 * processing client-side input
	 */

	public void run() {

		playerID = server.addPlayer(this);
		if (playerID != -1) { // -1 means adding the player was rejected
			if(playerID > 1) {
				server.tellOther(playerID, "added " + playerID);
				server.getFromOther(playerID, "previously added: " + (playerID-1));
			}
			sendMessage("ok " + playerID);
			if(server.enoughPlayers()) {
				server.startTheGame();
			}
			processPlayerInput();

			server.removePlayer(playerID); // remove player from server data
			server.tellOther(playerID, "removed " + playerID); // tell others
		} else {
			// game is full
			sendMessage("full");
		}

		try { // close socket from player
			clientSock.close();
			System.out.println("Player " + playerID + " connection closed\n");
		} catch (Exception e) {
			System.out.println(e);
		}
	}
	
	/* Stop when the input stream closes (is null) or "disconnect" is sent.
    Otherwise pass the input to doRequest(). */
	private void processPlayerInput() {
		String line;
		boolean done = false;
		try {
			while (!done) {
				if ((line = in.readLine()) == null)
					done = true;
				else {
					 System.out.println("Player " + playerID + " msg: " + line);
					if (line.trim().equals("disconnect"))
						done = true;
					else
						doRequest(line);
				}
			}
		} catch (IOException e) {
			System.out.println("Player " + playerID + " closed the connection");
		}
	}

	 /* The input line can be :
    	try <posn>    -- try to occupy position pos (pos == 0-63)

 		No checking of posn done here; we assume the client has checked it.
 		No checking of turn order here; we assume the client is doing it
	 */
	private void doRequest(String line) {
		if (line.startsWith("other played")) {
			try {
				System.out.println("DO the request");
				int playerID = Integer.valueOf(line.substring(13, 14));
				int otherPlayerID = ((playerID == 1) ? 2 : 1);
				String move = line.substring(15);
				
				//int posn = Integer.parseInt(line.substring(13).trim());
				// System.out.println("Player " + playerID + wants to occupy position " + posn);

				if (server.enoughPlayers())
					server.tellOther(otherPlayerID, "otherTurn " + move); // pass turn to others
				else
					sendMessage("tooFewPlayers");
			} catch (NumberFormatException e) {
				System.out.println(e);
			}
		}
	}

	// called by handler and top-level server
	synchronized public void sendMessage(String msg) {
		try {
			out.println(msg);
		} catch (Exception e) {
			System.out.println("Handler for player " + playerID + "\n" + e);
		}
	}

}
